<?php
namespace zake\helper;

use zake\foundation\able\ListAble;


/**
 * Class Grant
 * @package zake\helper
 *
 * 访问守卫
 *
 * 1: 当有客户端连接时，发放当前连接句柄的 connect id
 * 2: 创建子进程时，发放子进程的 process id
 */
class Grant
{

    // 最大连接数.
    const MAX_ACCEPT_NUM = 65535;// 65536. 保证16 bit

    // 最大进程数.
    const MAX_PROCESS_NUM = 8;// 256. 保证8 bit


    /**
     * @var null|ListAble
     */
    private static $connectGrant = null;


    /**
     * @var null |ListAble
     */
    private static $processGrant = null;


    /**
     * 授权 connect id
     *
     * @author liu.bin 2020-03-30 18:40
     */
    public static function permitConnectId()
    {
        $grant = self::getConnectGrant();
        if($grant->isEmpty()){
            return 0;
        }
        return $grant->pop();
    }

    /**
     * 收回 accept id
     *
     * @author liu.bin 2020-03-30 18:57
     */
    public static function recoveryConnectId($connectId)
    {
        $grant = self::getConnectGrant();
        if($grant->size() >= self::MAX_ACCEPT_NUM){
            return 0;
        }
        if($grant->has($connectId)){
            return true;
        }
        return $grant->push($connectId);
    }


    /**
     * 获取当前剩余的 accept id 数量
     * @return int
     *
     * @author liu.bin 2020-03-30 19:38
     */
    public static function connectSize()
    {
        return self::getConnectGrant()->size();
    }


    /**
     * 初始化
     * @param null|int $num
     * @return int|mixed
     *
     * @author liu.bin 2020-03-30 19:01
     */
    public static function connectInit($num=null)
    {
        $grant = self::getConnectGrant();
        $grant->empty();
        $num = is_null($num) ? self::MAX_PROCESS_NUM : $num;
        for ($i=1; $i <= $num ;$i++){
            $grant->push($i);
        }
        return true;
    }

//-------------------------------------------------


    /**
     * 授权 process id
     *
     * @author liu.bin 2020-03-30 18:40
     */
    public static function permitProcessId()
    {
        $grant = self::getProcessGrant();
        if($grant->isEmpty()){
            return 0;
        }
        return $grant->pop();
    }

    /**
     * 收回 process id
     * @param int $processId
     * @return bool
     * @author liu.bin 2020-03-30 18:57
     */
    public static function recoveryProcessId($processId)
    {
        $grant = self::getProcessGrant();
        if($grant->size() >= self::MAX_PROCESS_NUM){
            return 0;
        }
        if($grant->has($processId)){
            return true;
        }
        return $grant->push($processId);
    }


    /**
     * 初始化进程数量
     * @return int|mixed
     *
     * @author liu.bin 2020-03-30 19:01
     */
    public static function processInit($num=null)
    {
        $grant = self::getProcessGrant();
        $grant->empty();
        $num = is_null($num) ? self::MAX_PROCESS_NUM : $num;
        for ($i=1; $i <= $num ;$i++){
            $grant->push($i);
        }
        return true;
    }


    /**
     * 获取当前剩余的 进程 数量
     * @return int
     *
     * @author liu.bin 2020-03-30 19:38
     */
    public static function processSize()
    {
        return self::getProcessGrant()->size();
    }


    //-------------------------------------------------

    /**
     *
     * @return ListAble
     *
     * @author liu.bin 2020-03-24 23:30
     */
    private static function getConnectGrant()
    {
        if(is_null(static::$connectGrant)){
            static::$connectGrant = new ArrayList();
        }
        return static::$connectGrant;
    }


    /**
     *
     * @return ListAble
     *
     * @author liu.bin 2020-03-24 23:30
     */
    private static function getProcessGrant()
    {
        if(is_null(static::$processGrant)){
            static::$processGrant = new ArrayList();
        }
        return static::$processGrant;
    }


}